/**
  * @file	usart.c
  *	@author	yoyoyes
  * @date	2023-6-3
  */

#include "usart.h"
#include "systick.h"
#include "stdarg.h"
#include "string.h"
#include "gd32f10x.h"

uint8_t usart0_rx_buff[USART0_RX_BUFF_SIZE];				/* 串口0 接收缓冲区 */
uint8_t usart0_tx_buff[USART0_TX_BUFF_SIZE];				/* 串口0 发送缓冲区 */
usart_rx_control_block_struct usart0_rx_control_block;		/* 串口0 数据接收控制体 */

uint8_t usart2_rx_buff[USART2_RX_BUFF_SIZE];				/* 串口2 接收缓冲区 */
uint8_t usart2_tx_buff[USART2_TX_BUFF_SIZE];				/* 串口2 发送缓冲区 */
usart_rx_control_block_struct usart2_rx_control_block;		/* 串口2 数据接收控制体 */

uint8_t usart0_rx_frame[USART0_RX_MAX];						/* 串口0 接收数据帧 */
uint8_t usart2_rx_frame[USART2_RX_MAX];						/* 串口2 接收数据帧 */

/**
  * @func	usart0_init
  * @param	bandrate	比特率
  * @return	none
  */
void gd_hal_usart0_init(unsigned int bandrate)
{
	/* 串口0 时钟使能 */
	rcu_periph_clock_enable(RCU_USART0);							
	rcu_periph_clock_enable(RCU_GPIOA);
	
	/* 串口0 gpio初始化 */
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
	gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
	
	/* 串口0 参数配置 */
	usart_deinit(USART0);
	usart_baudrate_set(USART0, bandrate);
	usart_parity_config(USART0, USART_PM_NONE);
	usart_word_length_set(USART0, USART_WL_8BIT);
	usart_stop_bit_set(USART0, USART_STB_1BIT);
	usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
	usart_receive_config(USART0, USART_RECEIVE_ENABLE);
	
	/* 串口0 DMA接收使能 */
	usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);
	
	/* 串口0 中断优先级设置 */
	nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
	nvic_irq_enable(USART0_IRQn, 0, 0);
	
	/* 串口0 空闲中断使能 */
	usart_interrupt_enable(USART0, USART_INT_IDLE);
	
	/* 串口0 使能*/
	usart_enable(USART0);
}

/**
  * @func	usart2_init
  * @param	bandrate	比特率
  * @return	none
  */
void gd_hal_usart2_init(unsigned int bandrate)
{
	/* 串口2 时钟使能 */
	rcu_periph_clock_enable(RCU_USART2);							
	rcu_periph_clock_enable(RCU_GPIOB);
	
	/* 串口2 gpio初始化 */
	gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
	gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
	
	/* 串口2 参数配置 */
	usart_deinit(USART2);
	usart_baudrate_set(USART2, bandrate);
	usart_parity_config(USART2, USART_PM_NONE);
	usart_word_length_set(USART2, USART_WL_8BIT);
	usart_stop_bit_set(USART2, USART_STB_1BIT);
	usart_transmit_config(USART2, USART_TRANSMIT_ENABLE);
	usart_receive_config(USART2, USART_RECEIVE_ENABLE);
	
	/* 串口2 DMA接收使能 */
	usart_dma_receive_config(USART2, USART_RECEIVE_DMA_ENABLE);
	
	/* 串口2 中断优先级设置 */
	nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
	nvic_irq_enable(USART2_IRQn, 0, 0);
	
	/* 串口2 空闲中断使能 */
	usart_interrupt_enable(USART2, USART_INT_IDLE);
	
	/* 串口2 使能*/
	usart_enable(USART2);
}

/**
  * @func	usart0_printf
  * @param	format		格式化字符串指针
  * @param  ...			不定个数参数
  * @return	none
  */
void usart0_printf(char *format, ...)
{
	uint16_t i;
	va_list list_data;
	
	va_start(list_data, format);
	vsprintf((char *)usart0_tx_buff, format, list_data);
	va_end(list_data);
	
	for(i = 0; i < strlen((const char *)usart0_tx_buff); i++)
	{
		while(usart_flag_get(USART0, USART_FLAG_TBE) != 1);
		usart_data_transmit(USART0, usart0_tx_buff[i]);
	}
	
	while(usart_flag_get(USART0, USART_FLAG_TC) != 1);
}

/**
  * @func	usart2_printf
  * @param	format		格式化字符串指针
  * @param  ...			不定个数参数
  * @return	none
  */
void usart2_printf(char *format, ...)
{
	uint16_t i;
	va_list list_data;
	
	va_start(list_data, format);
	vsprintf((char *)usart2_tx_buff, format, list_data);
	va_end(list_data);
	
	for(i = 0; i < strlen((const char *)usart2_tx_buff); i++)
	{
		while(usart_flag_get(USART2, USART_FLAG_TBE) != 1);
		usart_data_transmit(USART2, usart2_tx_buff[i]);
	}
	
	while(usart_flag_get(USART2, USART_FLAG_TC) != 1);
}

/**
  * @func	rx_control_block_init
  * @param	cb	USARTx(x = 0, 1, 2) 控制体指针
  * @param	usart_rx_buff	USARTx(x = 0, 1, 2) 接收缓冲区指针
  * @return	none
  */
void rx_control_block_init(usart_rx_control_block_struct *cb, uint8_t *usart_rx_buff)
{
	cb->rx_byte_counter = 0;													/* 接收缓冲区数据量 */
	cb->rx_buff_write = &cb->rx_buff_se_list[0];								/* 写数据指针指向列表的第一个标志 */
	cb->rx_buff_read  = &cb->rx_buff_se_list[0];								/* 读数据指针指向列表的第一个标志 */
	cb->rx_buff_write->start = usart_rx_buff;									/* 写数据的起始指针指向接收缓冲区的起始地址 */
	cb->rx_buff_se_list_full = &cb->rx_buff_se_list[RX_BUFF_SE_LIST_SIZE - 1];	/* 列表满指针指向列表的最后一个标志*/
}

/**
  * @func	usart_rx_frame_read
  * @param  cb		USARTx(x = 0, 1, 2) 控制体指针
  * @param	buff	数据指针
  * @return	数据长度
  */
int usart_rx_frame_read(usart_rx_control_block_struct *cb, uint8_t *buff)
{
	uint16_t len = 0;
	
	if(cb->rx_buff_read != cb->rx_buff_write)
	{
		len = cb->rx_buff_read->end - cb->rx_buff_read->start + 1;
			
		/* 提取数据处理 */
		if(buff == usart0_rx_frame)
		{
			memset(buff, 0, USART0_RX_MAX);
		}
		else if(buff == usart2_rx_frame)
		{
			memset(buff, 0, USART2_RX_MAX);
		}
		memcpy(buff, cb->rx_buff_read->start, len);
				
		/* 读指针往后移动 */
		cb->rx_buff_read++;
		if(cb->rx_buff_read == cb->rx_buff_se_list_full)
		{
			cb->rx_buff_read = &cb->rx_buff_se_list[0];
		}
	}
	
	return len;
}

/**
  * @func	usart_rx_frame_read
  * @param  cb		USARTx(x = 0, 1, 2) 控制体指针
  * @param	buff	数据指针
  * @param  timeout_ms		超时时间
  * @return	数据长度
  */
int usart_rx_frame_timeout_read(usart_rx_control_block_struct *cb, uint8_t *buff, uint16_t timeout_ms)
{
	uint16_t len = 0;
	
	do {
		len = usart_rx_frame_read(cb, buff);
		systick_delay_ms(1);
	} while(!len && timeout_ms--);
	
	return len;
}

/**
  * @func	usart0_getchar
  * @param	none
  * @return	字符数据
  */
char usart0_getchar(void)
{
	while(!usart_rx_frame_read(&usart0_rx_control_block, usart0_rx_frame));
	
	return usart0_rx_frame[0];
}

/**
  * @func	usart0_gets
  * @param	buff		数据指针
  * @param	buff_len	数据长度
  * @return	数据首地址
  */
char *usart0_gets(char *buff, uint16_t buff_len)
{
	char ch;
	char *p = buff;
	
	memset(buff, 0, buff_len);
	
	while((ch = usart0_getchar()) != '\r')
	{
		if(ch != '\b')
		{
			usart0_printf("%c", ch);
			*buff++ = ch;
		}
		else
		{
			if(buff > p)
			{
				usart0_printf("\b");
				usart0_printf(" ");
				usart0_printf("\b");
				buff--;
				*buff = '\0';
			}
		}
	}
	
	*buff = '\0';
	usart0_printf("\r\n");
	
	return p;
}

/**
  * @func	gd_hal_usart_init
  * @param	none
  * @return	none
  */
void gd_hal_usart_init(void)
{
	gd_hal_usart0_init(115200);
	gd_hal_usart2_init(115200);
	rx_control_block_init(&usart0_rx_control_block, usart0_rx_buff);
	rx_control_block_init(&usart2_rx_control_block, usart2_rx_buff);
}

/**
  * @func	USART0_IRQHandler
  * @param	none
  * @return	none
  */
void USART0_IRQHandler(void)
{
	if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) != 0)
	{
		/* 清除中断标志 */
		usart_flag_get(USART0, USART_FLAG_IDLEF);
		usart_data_receive(USART0);
		
		/* 缓冲区接收数据量 */
		usart0_rx_control_block.rx_byte_counter += USART0_DMA_TRANSFER_SIZE - dma_transfer_number_get(DMA0, DMA_CH4);
		
		/* 记录本次写入数据的结束地址 */
		usart0_rx_control_block.rx_buff_write->end = &usart0_rx_buff[usart0_rx_control_block.rx_byte_counter - 1];
		usart0_rx_control_block.rx_buff_write++;											
		if(usart0_rx_control_block.rx_buff_write >= usart0_rx_control_block.rx_buff_se_list_full)
		{
			usart0_rx_control_block.rx_buff_write = &usart0_rx_control_block.rx_buff_se_list[0];
		}
		
		/* 记录下一次写入数据的地址 */
		if(USART0_RX_BUFF_SIZE - usart0_rx_control_block.rx_byte_counter >= USART0_RX_MAX)
		{
			usart0_rx_control_block.rx_buff_write->start = &usart0_rx_buff[usart0_rx_control_block.rx_byte_counter];	
		}
		else
		{
			usart0_rx_control_block.rx_buff_write->start = usart0_rx_buff;
			usart0_rx_control_block.rx_byte_counter = 0;
		}
		
		/* 开启下一次DMA传输 */
		dma_channel_disable(DMA0, DMA_CH4);
		dma_transfer_number_config(DMA0, DMA_CH4, USART0_DMA_TRANSFER_SIZE);
		dma_memory_address_config(DMA0, DMA_CH4, (uint32_t)usart0_rx_control_block.rx_buff_write->start);
		dma_channel_enable(DMA0, DMA_CH4);
	}
}

/**
  * @func	USART2_IRQHandler
  * @param	none
  * @return	none
  */
void USART2_IRQHandler(void)
{
	if(usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE) != 0)
	{
		/* 清除中断标志 */
		usart_flag_get(USART2, USART_FLAG_IDLEF);
		usart_data_receive(USART2);
		
		/* 缓冲区接收数据量 */
		usart2_rx_control_block.rx_byte_counter += USART2_DMA_TRANSFER_SIZE - dma_transfer_number_get(DMA0, DMA_CH2);
		
		/* 记录本次写入数据的结束地址 */
		usart2_rx_control_block.rx_buff_write->end = &usart2_rx_buff[usart2_rx_control_block.rx_byte_counter - 1];
		usart2_rx_control_block.rx_buff_write++;											
		if(usart2_rx_control_block.rx_buff_write >= usart2_rx_control_block.rx_buff_se_list_full)
		{
			usart2_rx_control_block.rx_buff_write = &usart2_rx_control_block.rx_buff_se_list[0];
		}
		
		/* 记录下一次写入数据的地址 */
		if(USART2_RX_BUFF_SIZE - usart2_rx_control_block.rx_byte_counter >= USART2_RX_MAX)
		{
			usart2_rx_control_block.rx_buff_write->start = &usart2_rx_buff[usart2_rx_control_block.rx_byte_counter];	
		}
		else
		{
			usart2_rx_control_block.rx_buff_write->start = usart2_rx_buff;
			usart2_rx_control_block.rx_byte_counter = 0;
		}
		
		/* 开启下一次DMA传输 */
		dma_channel_disable(DMA0, DMA_CH2);
		dma_transfer_number_config(DMA0, DMA_CH2, USART2_DMA_TRANSFER_SIZE);
		dma_memory_address_config(DMA0, DMA_CH2, (uint32_t)usart2_rx_control_block.rx_buff_write->start);
		dma_channel_enable(DMA0, DMA_CH2);
	}
}
